home *** CD-ROM | disk | FTP | other *** search
/ QRZ! Ham Radio 8 / QRZ Ham Radio Callsign Database - Volume 8.iso / mac / files / t_sys5 / 92052tar.gz / 920528.tar / mail_smtp.c < prev    next >
C/C++ Source or Header  |  1991-06-04  |  5KB  |  206 lines

  1. /* @(#) $Header: mail_smtp.c,v 1.8 91/06/04 11:34:25 deyke Exp $ */
  2.  
  3. /* SMTP Mail Delivery Agent */
  4.  
  5. #include <stdio.h>
  6. #include <stdlib.h>
  7. #include <string.h>
  8. #include <unistd.h>
  9.  
  10. #include "global.h"
  11. #include "mbuf.h"
  12. #include "transport.h"
  13. #include "mail.h"
  14.  
  15. struct mesg {
  16.   int  state;
  17. #define SMTP_OPEN_STATE 0
  18. #define SMTP_HELO_STATE 1
  19. #define SMTP_MAIL_STATE 2
  20. #define SMTP_RCPT_STATE 3
  21. #define SMTP_DATA_STATE 4
  22. #define SMTP_SEND_STATE 5
  23. #define SMTP_UNLK_STATE 6
  24. #define SMTP_QUIT_STATE 7
  25.   char  buf[1024];
  26.   int  cnt;
  27.   FILE * fp;
  28.   struct mailsys *sp;
  29.   struct transport_cb *tp;
  30. };
  31.  
  32. static void mail_smtp_transaction __ARGS((struct mesg *mp));
  33. static void mail_smtp_recv_upcall __ARGS((struct transport_cb *tp, int cnt));
  34. static void mail_smtp_send_upcall __ARGS((struct transport_cb *tp, int cnt));
  35. static void mail_smtp_state_upcall __ARGS((struct transport_cb *tp));
  36.  
  37. /*---------------------------------------------------------------------------*/
  38.  
  39. static void mail_smtp_transaction(mp)
  40. struct mesg *mp;
  41. {
  42.  
  43.   char  tmp[1024];
  44.   struct mailjob *jp;
  45.  
  46.   jp = mp->sp->jobs;
  47.   if (mp->state == SMTP_OPEN_STATE && (*mp->buf < '0' || *mp->buf > '9')) return;
  48.   if (*mp->buf == (mp->state == SMTP_DATA_STATE ? '3' : '2'))
  49.     switch (mp->state) {
  50.     case SMTP_OPEN_STATE:
  51.       mp->state = SMTP_HELO_STATE;
  52.       sprintf(tmp, "helo %s\n", Hostname);
  53.       transport_send(mp->tp, qdata(tmp, strlen(tmp)));
  54.       break;
  55.     case SMTP_HELO_STATE:
  56. nextjob:
  57.       mp->state = SMTP_MAIL_STATE;
  58.       sprintf(tmp,
  59.           "mail from:<%s@%s>\n",
  60.           get_user_from_path(jp->from),
  61.           get_host_from_path(jp->from));
  62.       transport_send(mp->tp, qdata(tmp, strlen(tmp)));
  63.       break;
  64.     case SMTP_MAIL_STATE:
  65.       mp->state = SMTP_RCPT_STATE;
  66.       sprintf(tmp,
  67.           "rcpt to:<%s@%s>\n",
  68.           get_user_from_path(jp->to),
  69.           get_host_from_path(jp->to));
  70.       transport_send(mp->tp, qdata(tmp, strlen(tmp)));
  71.       break;
  72.     case SMTP_RCPT_STATE:
  73.       mp->state = SMTP_DATA_STATE;
  74.       transport_send(mp->tp, qdata("data\n", 5));
  75.       break;
  76.     case SMTP_DATA_STATE:
  77.       if (mp->fp = fopen(jp->dfile, "r")) {
  78.     mp->state = SMTP_SEND_STATE;
  79.     fgets(tmp, sizeof(tmp), mp->fp);
  80.     mail_smtp_send_upcall(mp->tp, transport_send_space(mp->tp));
  81.       } else {
  82.     mp->state = SMTP_QUIT_STATE;
  83.     transport_close(mp->tp);
  84.       }
  85.       break;
  86.     case SMTP_SEND_STATE:
  87.       break;
  88.     case SMTP_UNLK_STATE:
  89.       unlink(jp->cfile);
  90.       unlink(jp->dfile);
  91.       unlink(jp->xfile);
  92.       mp->sp->jobs = jp->next;
  93.       free(jp);
  94.       if (jp = mp->sp->jobs) goto nextjob;
  95.       mp->state = SMTP_QUIT_STATE;
  96.       transport_send(mp->tp, qdata("quit\n", 5));
  97.       break;
  98.     case SMTP_QUIT_STATE:
  99.       transport_close(mp->tp);
  100.       break;
  101.     }
  102.   else {
  103.     if (mp->state != SMTP_QUIT_STATE) {
  104.       strcpy(jp->return_reason, mp->buf);
  105.       mail_return(jp);
  106.       mp->state = SMTP_QUIT_STATE;
  107.       transport_send(mp->tp, qdata("quit\n", 5));
  108.     }
  109.     transport_close(mp->tp);
  110.   }
  111. }
  112.  
  113. /*---------------------------------------------------------------------------*/
  114.  
  115. static void mail_smtp_recv_upcall(tp, cnt)
  116. struct transport_cb *tp;
  117. int  cnt;
  118. {
  119.  
  120.   int  c;
  121.   struct mbuf *bp;
  122.   struct mesg *mp;
  123.  
  124.   mp = (struct mesg *) tp->user;
  125.   mp->sp->state = MS_TALKING;
  126.   transport_recv(tp, &bp, 0);
  127.   while ((c = PULLCHAR(&bp)) != -1)
  128.     if (c == '\n') {
  129.       mp->buf[mp->cnt] = '\0';
  130.       mail_smtp_transaction(mp);
  131.       mp->cnt = 0;
  132.     }
  133.     else if (mp->cnt < sizeof(mp->buf) - 1)
  134.       mp->buf[mp->cnt++] = c;
  135. }
  136.  
  137. /*---------------------------------------------------------------------------*/
  138.  
  139. static void mail_smtp_send_upcall(tp, cnt)
  140. struct transport_cb *tp;
  141. int  cnt;
  142. {
  143.  
  144.   char  *p;
  145.   int  c;
  146.   struct mbuf *bp;
  147.   struct mesg *mp;
  148.  
  149.   mp = (struct mesg *) tp->user;
  150.   if (mp->state != SMTP_SEND_STATE || cnt <= 0) return;
  151.   if (!(bp = alloc_mbuf(cnt))) return;
  152.   p = bp->data;
  153.   while (p - bp->data < cnt && (c = getc(mp->fp)) != EOF)
  154.     if (c && c != '\004' && c != '\032') *p++ = c;
  155.   if (bp->cnt = p - bp->data)
  156.     transport_send(tp, bp);
  157.   else
  158.     free_p(bp);
  159.   if (c == EOF) {
  160.     fclose(mp->fp);
  161.     mp->fp = 0;
  162.     transport_send(mp->tp, qdata(".\n", 2));
  163.     mp->state = SMTP_UNLK_STATE;
  164.   }
  165. }
  166.  
  167. /*---------------------------------------------------------------------------*/
  168.  
  169. static void mail_smtp_state_upcall(tp)
  170. struct transport_cb *tp;
  171. {
  172.   struct mesg *mp;
  173.  
  174.   if (mp = (struct mesg *) tp->user) {
  175.     if (mp->fp) fclose(mp->fp);
  176.     if (!mp->sp->jobs)
  177.       mp->sp->state = MS_SUCCESS;
  178.     else
  179.       mailer_failed(mp->sp);
  180.     free(mp);
  181.   }
  182.   transport_del(tp);
  183. }
  184.  
  185. /*---------------------------------------------------------------------------*/
  186.  
  187. void mail_smtp(sp)
  188. struct mailsys *sp;
  189. {
  190.   struct mesg *mp;
  191.  
  192.   mp = calloc(1, sizeof(*mp));
  193.   mp->sp = sp;
  194.   if (mp->tp = transport_open(sp->protocol, sp->address, mail_smtp_recv_upcall, mail_smtp_send_upcall, mail_smtp_state_upcall, (char *) mp)) {
  195.     mp->tp->recv_mode = EOL_LF;
  196.     mp->tp->send_mode = strcmp(sp->protocol, "tcp") ? EOL_CR : EOL_CRLF;
  197.     transport_set_timeout(mp->tp, 3600);
  198.     if (strcmp(sp->protocol, "tcp"))
  199.       transport_send(mp->tp, qdata("cmd.smtp\n", 9));
  200.   } else {
  201.     mailer_failed(sp);
  202.     free(mp);
  203.   }
  204. }
  205.  
  206.